//main.js
const fs = require('fs/promises');
const NativeModule = require('module')
const vm = require('vm')
const path = require('path');
// 定义 scripts 目录路径 
const SCRIPT_DIR = 'scripts'
 
// 单个加载
const loadScript2Context = async (fileName) => {  
    const jsContext = await fs.readFile( fileName, 'utf-8')
    // console.log('jsContext',jsContext)
    const m = { exports: {} }
    const wrapper = NativeModule.wrap(jsContext)
    const script = new vm.Script(wrapper, { 
      fileName,
        displayErrors: true
    })
    const result = script.runInThisContext() // 指定代码的执行上下文
    result.call(m.exports, m.exports, require, m) // 执行wrapper函数，解决不能require的问题
    return m
}

// 加载所有
exports.loadScriptModules = async () => { 
    try {
        // 读取目录内容 
      // 读取目录内容
      const dirents = await fs.readdir(path.join(__dirname, SCRIPT_DIR), { withFileTypes: true });
      
      // 过滤出 .js 文件
      const jsFiles = dirents
        .filter(dirent => dirent.isFile() && dirent.name.endsWith('.js'))
      ; 
      let mods = {}
      for (const f of jsFiles) { 
        // console.log('f',f)
          let fileName = path.join(__dirname,SCRIPT_DIR, f.name); 
          let fileKey = f.name.replace(new RegExp('.js$'),'')
          //  console.log('fileKey',fileKey, 'fileName',fileName)
          let m = await loadScript2Context(fileName) 
          mods[fileKey] = m;
      }
      return mods; 
    } catch (err) {
        console.error('❌ 读取目录或执行脚本失败:', err);
   }
}
 
 

exports.dynamicCall = (targetObj, command) => {
  // 正则解析指令（匹配 模块对象.方法名(参数) 格式）
  // console.log(command)
  const regex = /^(\w+)\.(\w+)\((.*)\)$/; 
  const matchResult = command.match(regex);
  if (!matchResult) {
      throw new Error(`无效的调用指令格式，需为 '模块文件名.方法名(参数)'`);
  } 
  // 提取方法名和原始参数字符串
  const [_,objName, methodName, rawArgsStr] = matchResult;
  // console.log( _,objName, methodName, rawArgsStr)
  // 校验目标对象是否有该方法
  if (!targetObj.hasOwnProperty(methodName) || typeof targetObj[methodName] !== 'function') {
      throw new Error(`对象 ${objName} 不存在可调用的方法：${methodName}`);
  }
  // 参数列表转json数组
  let tempArgStrs = `[${rawArgsStr}]`
  let parsedArgs = [];
  try {
    parsedArgs = JSON.parse(tempArgStrs)
  } catch (e) { 
     throw new Error(`参数错误，请认真检查： ${rawArgsStr}`);
  } 
  return targetObj[methodName].apply(targetObj, parsedArgs);
}